<?php


namespace helper;


class Xml
{

    /**
     * 生成xml
     * @param $data
     * @return mixed|\SimpleXMLElement
     */
    static public function data2xml($data)
    {
        $xml = new \SimpleXMLElement('<xml></xml>');
        self::_data_to_xml($xml, $data);
        $xml = $xml->asXML();
        return $xml;
    }

    /**
     * XML转数组
     * @param string $xml XML内容
     * @return array
     */
    static public function xml2data($xml)
    {
        $values = array();
        $index  = array();
        $array  = array();
        $parser = xml_parser_create('utf-8');
        xml_parser_set_option($parser, XML_OPTION_SKIP_WHITE, 1);
        xml_parser_set_option($parser, XML_OPTION_CASE_FOLDING, 0);
        xml_parse_into_struct($parser, $xml, $values, $index);
        xml_parser_free($parser);
        $i            = 0;
        $name         = $values[$i]['tag'];
        $array[$name] = isset($values[$i]['attributes']) ? $values[$i]['attributes'] : '';
        $array[$name] = self::_xml_to_data($values, $i);
        return $array;
    }

    /**
     * 数据XML编码
     * @param object $xml XML对象
     * @param mixed $data 数据
     * @param string $item 数字索引时的节点名称
     */
    static public function _data_to_xml($xml, $data, $item = 'item')
    {
        foreach ($data as $key => $value) {
            /* 指定默认的数字key */
            is_numeric($key) && $key = $item;
            /* 添加子元素 */
            if (is_array($value) || is_object($value)) {
                $child = $xml->addChild($key);
                self::_data_to_xml($child, $value, $item);
            } else {
                if (is_numeric($value)) {
                    $child = $xml->addChild($key, $value);
                } else {
                    $child = $xml->addChild($key);
                }
                $node  = dom_import_simplexml($child);
                $cdata = $node->ownerDocument->createCDATASection($value);
                $node->appendChild($cdata);
            }
        }
    }

    /**
     * 节点转换
     * @param array $values XML数据
     * @param integer &$i 指针
     * @return array
     */
    static private function _xml_to_data($values, &$i)
    {
        $child = array();
        if (isset($values[$i]['value'])) array_push($child, $values[$i]['value']);
        while ($i++ < count($values)) {
            switch ($values[$i]['type']) {
                case 'cdata':
                    array_push($child, $values[$i]['value']);
                    break;
                case 'complete':
                    $name = $values[$i]['tag'];
                    if (!empty($name)) {
                        $child[$name] = ($values[$i]['value']) ?: '';
                        if (isset($values[$i]['attributes'])) {
                            $child[$name] = $values[$i]['attributes'];
                        }
                    }
                    break;
                case 'open':
                    $name                = $values[$i]['tag'];
                    $size                = isset($child[$name]) ? sizeof($child[$name]) : 0;
                    $child[$name][$size] = self::_xml_to_data($values, $i);
                    break;
                case 'close':
                    return $child;
            }
        }
        return $child;
    }
}